from datetime import datetime
from typing import List, Tuple
from fastapi import HTTPException, UploadFile
from tortoise.contrib.pydantic import pydantic_model_creator, PydanticModel
from model.sysRoleMenuModel import SysRoleMenu
from schema.sysRoleMenuSchema import SysRoleMenuCreate, SysRoleMenuUpdate, PageParams
from io import BytesIO
from excel.sysRoleMenuExcel import SysRoleMenuExcel


class PydanticConfig:
    alias_generator = lambda x: ''.join(word.capitalize() if i else word for i, word in enumerate(x.split('_')))
    allow_population_by_field_name = True


SysRoleMenu_Pydantic = pydantic_model_creator(SysRoleMenu, name="SysRoleMenu", config_class=PydanticConfig)


class SysRoleMenuService:
    def __init__(self):
        self.model = SysRoleMenu
        self.excel = SysRoleMenuExcel

    @staticmethod
    async def create(data: SysRoleMenuCreate, creator: str) -> SysRoleMenu:
        """Create new record"""
        data_dict = data.dict(exclude_unset=True)
        data_dict["create_by"] = creator
        data_dict["create_time"] = datetime.now()
        data_dict["status"] = '0'

        obj = await SysRoleMenu.create(**data_dict)
        return await SysRoleMenu_Pydantic.from_tortoise_orm(obj)

    @staticmethod
    async def get_by_id(id: int) -> SysRoleMenu:
        """Get record by ID"""
        obj = await SysRoleMenu.get_or_none(role_id=id, status='0')
        if not obj:
            raise HTTPException(status_code=404, detail="角色和菜单关联表不存在")
        return await SysRoleMenu_Pydantic.from_tortoise_orm(obj)

    @staticmethod
    async def update(id: int, data: SysRoleMenuUpdate, updater: str) -> SysRoleMenu:
        """Update record"""
        obj = await SysRoleMenu.get_or_none(role_id=id, status='0')
        if not obj:
            raise HTTPException(status_code=404, detail="角色和菜单关联表不存在")

        update_dict = data.dict(exclude_unset=True)
        update_dict["update_by"] = updater
        update_dict["update_time"] = datetime.now()

        await obj.update_from_dict(update_dict).save()
        return await SysRoleMenu_Pydantic.from_tortoise_orm(obj)

    @staticmethod
    async def delete(ids: List[int], updater: str) -> int:
        """Batch delete records"""
        update_data = {
            "status": '2',
            "update_by": updater,
            "update_time": datetime.now()
        }
        count = await SysRoleMenu.filter(role_id__in=ids, status='0').update(**update_data)
        return count

    @staticmethod
    async def get_page(params: PageParams) -> Tuple[List[SysRoleMenu], int]:
        """Get page list"""
        query = SysRoleMenu.filter(status='0')

        # Build query conditions


        total = await query.count()

        records = await query.offset((params.page_num - 1) * params.page_size)             .limit(params.page_size)             .order_by("-create_time")

        return [await SysRoleMenu_Pydantic.from_tortoise_orm(record) for record in records], total

    @staticmethod
    async def export_excel() -> BytesIO:
        """Export all data to Excel"""
        records = await SysRoleMenu.filter(status='0').all()
        return await SysRoleMenuExcel.export_data(records)

    @staticmethod
    def get_import_template() -> BytesIO:
        """Get import template"""
        return SysRoleMenuExcel.get_import_template()

    @staticmethod
    async def import_data(file: UploadFile, creator: str) -> Tuple[int, List[str]]:
        """Import data"""
        content = await file.read()
        file_bytes = BytesIO(content)

        try:
            data_list = SysRoleMenuExcel.parse_import_data(file_bytes)
        except ValueError as e:
            raise HTTPException(status_code=400, detail=str(e))
        except Exception as e:
            raise HTTPException(status_code=400, detail="Excel文件格式错误")

        success_count = 0
        error_msgs = []

        for index, item_data in enumerate(data_list, start=1):
            try:
                item_data['create_by'] = creator
                item_data['create_time'] = datetime.now()
                item_data['status'] = '0'

                await SysRoleMenu.create(**item_data)
                success_count += 1

            except Exception as e:
                error_msgs.append(f"第{index}行: {str(e)}")

        return success_count, error_msgs

    async def batch_create_by_dept_list(self, role_id: int, menu_id_list: List[int], creator: str) -> List[PydanticModel]:
        """
        Batch create user-role associations for multiple users with one role

        Args:
            role_id: The ID of the role
            menu_id_list: List of menu IDs to associate with the role
            creator: The creator of these associations

        Returns:
            List of created user-role association records
        """

        await self.model.filter(role_id=role_id).delete()

        current_time = datetime.now()
        created_records = []

        base_data = {
            "role_id": role_id,
            "create_by": creator,
            "create_time": current_time,
            "status": '0'
        }

        for menu_id in menu_id_list:
            data = base_data.copy()
            data["menu_id"] = menu_id
            obj = await self.model.create(**data)
            created_records.append(await SysRoleMenu_Pydantic.from_tortoise_orm(obj))

        return created_records
